<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 5.4.0">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">

<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Noto Serif SC:300,300italic,400,400italic,700,700italic|Source Code Pro:300,300italic,400,400italic,700,700italic&display=swap&subset=latin,latin-ext">
<link rel="stylesheet" href="/lib/font-awesome/css/all.min.css">

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"example.com","root":"/","scheme":"Pisces","version":"7.8.0","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":true,"show_result":true,"style":"flat"},"back2top":{"enable":true,"sidebar":false,"scrollpercent":true},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":false,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}}};
  </script>

  <meta name="description" content="Ray Wenderlich原文加笔记，该文讲述了Swift协议的继承，协议的默认实现，默认方法的重写，协议的扩展等新的属性。Swift中Protocol基本具备了calss的特性。允许继承、扩展等。原文链接">
<meta property="og:type" content="article">
<meta property="og:title" content="Introducing Protocol-Oriented Programming in Swift 3">
<meta property="og:url" content="http://example.com/2018/12/21/Swift/Introducing%20Protocol-Oriented%20Programming%20in%20Swift%203/index.html">
<meta property="og:site_name" content="HR&#39;s Blog">
<meta property="og:description" content="Ray Wenderlich原文加笔记，该文讲述了Swift协议的继承，协议的默认实现，默认方法的重写，协议的扩展等新的属性。Swift中Protocol基本具备了calss的特性。允许继承、扩展等。原文链接">
<meta property="og:locale" content="en_US">
<meta property="og:image" content="http://example.com/2018/12/21/Swift/Introducing%20Protocol-Oriented%20Programming%20in%20Swift%203/media/15295785730512/protocols-extend-480x280.png">
<meta property="og:image" content="http://example.com/2018/12/21/Swift/Introducing%20Protocol-Oriented%20Programming%20in%20Swift%203/media/15295785730512/secrets-480x178.png">
<meta property="article:published_time" content="2018-12-21T07:12:43.000Z">
<meta property="article:modified_time" content="2018-12-21T07:12:43.000Z">
<meta property="article:author" content="HR">
<meta property="article:tag" content="Ray Wenderlich">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="http://example.com/2018/12/21/Swift/Introducing%20Protocol-Oriented%20Programming%20in%20Swift%203/media/15295785730512/protocols-extend-480x280.png">

<link rel="canonical" href="http://example.com/2018/12/21/Swift/Introducing%20Protocol-Oriented%20Programming%20in%20Swift%203/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : false,
    isPost : true,
    lang   : 'en'
  };
</script>

  <title>Introducing Protocol-Oriented Programming in Swift 3 | HR's Blog</title>
  
    <script async src="https://www.googletagmanager.com/gtag/js?id=UA-61905451-1"></script>
    <script>
      if (CONFIG.hostname === location.hostname) {
        window.dataLayer = window.dataLayer || [];
        function gtag(){dataLayer.push(arguments);}
        gtag('js', new Date());
        gtag('config', 'UA-61905451-1');
      }
    </script>






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="Toggle navigation bar">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">HR's Blog</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
      <p class="site-subtitle" itemprop="description">Swimming 🏊 in the sea🌊of code!</p>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="main-menu menu">
        <li class="menu-item menu-item-home">

    <a href="/" rel="section"><i class="fa fa-home fa-fw"></i>Home</a>

  </li>
        <li class="menu-item menu-item-about">

    <a href="/about/" rel="section"><i class="fa fa-user fa-fw"></i>About</a>

  </li>
        <li class="menu-item menu-item-tags">

    <a href="/tags/" rel="section"><i class="fa fa-tags fa-fw"></i>Tags</a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/categories/" rel="section"><i class="fa fa-th fa-fw"></i>Categories</a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>Archives</a>

  </li>
  </ul>
</nav>




</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>
  <div class="reading-progress-bar"></div>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content post posts-expand">
            

    
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="en">
    <link itemprop="mainEntityOfPage" href="http://example.com/2018/12/21/Swift/Introducing%20Protocol-Oriented%20Programming%20in%20Swift%203/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="HR">
      <meta itemprop="description" content="Swimming 🏊 in the sea🌊of code!">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="HR's Blog">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          Introducing Protocol-Oriented Programming in Swift 3
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">Posted on</span>

              <time title="Created: 2018-12-21 15:12:43" itemprop="dateCreated datePublished" datetime="2018-12-21T15:12:43+08:00">2018-12-21</time>
            </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">In</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/Swift/" itemprop="url" rel="index"><span itemprop="name">Swift</span></a>
                </span>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
        <p>Ray Wenderlich原文加笔记，该文讲述了Swift协议的继承，协议的默认实现，默认方法的重写，协议的扩展等新的属性。<br>Swift中<code>Protocol</code>基本具备了<code>calss</code>的特性。允许继承、扩展等。<a target="_blank" rel="noopener" href="https://www.raywenderlich.com/148448/introducing-protocol-oriented-programming">原文链接</a></p>
<span id="more"></span>

<p>Protocol-Oriented Programming will help you fly!</p>
<p><em>Update Note:</em> This tutorial has been updated to Swift 3.0 by Niv Yahel. The original tutorial was written by <a target="_blank" rel="noopener" href="https://www.raywenderlich.com/u/kerber">Erik Kerber</a>.</p>
<p>Imagine you’re developing a racing game. You can drive a car, ride a motorcycle, or even fly a plane. A common approach to creating this type of application is by using <a target="_blank" rel="noopener" href="https://www.raywenderlich.com/81952/intro-object-oriented-design-swift-part-1">object oriented design</a>, encapsulating all of the logic inside of an object that gets inherited to all of those that share similarity.</p>
<p>This design approach works, but does come with some drawbacks. For example, if you add the ability to create machines that also require gas, birds that fly in the background, or anything else that may want to share game logic, there isn’t a good way to separate the functional components of vehicles into something reusable.</p>
<p>This scenario is where <em>protocols</em> really shine.</p>
<p>Swift has always let you specify interface guarantees on existing <code>class</code>, <code>struct</code> and <code>enum</code> types using <em>protocols</em>. This lets you interact with them generically. Swift 2 introduced a way to extend protocols and provide default implementations. Finally, Swift 3 improves operator conformance and uses these improvements for the new numeric protocols in the standard library.</p>
<p>Protocol are extremely powerful and can transform the way you write code. In this tutorial, you’ll explore the ways you can create and use protocols, as well as use <code>protocol-oriented programming</code> patterns to make your code more extensible.</p>
<p>You’ll also see how the Swift team was able to use protocol extensions to improve the Swift standard library itself, and how it impacts the code you write.</p>
<h2 id="Getting-Started"><a href="#Getting-Started" class="headerlink" title="Getting Started"></a>Getting Started</h2><p>Begin by creating a new playground. In Xcode, select <em>File</em>*New<em>*Playground…</em> and name the playground <em>SwiftProtocols</em>. You can select any platform, since all the code in this tutorial is platform-agnostic. Click <em>Next</em> to choose where you would like to save it, and finally click <em>Create</em>.</p>
<p>Once your new playground is open, add the following code to it:</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">protocol</span> <span class="title">Bird</span> </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> name: <span class="type">String</span> &#123; <span class="keyword">get</span> &#125;</span><br><span class="line">    <span class="keyword">var</span> canFly: <span class="type">Bool</span> &#123; <span class="keyword">get</span> &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">protocol</span> <span class="title">Flyable</span> </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> airspeedVelocity: <span class="type">Double</span> &#123; <span class="keyword">get</span> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>This defines a simple protocol <code>Bird</code> with properties <code>name</code> and <code>canFly</code>, as well as a <code>Flyable</code> protocol which defines <code>airspeedVelocity</code>.</p>
<p>In a pre-protocol world, you might have started with <code>Flyable</code> as a base class and then relied on object inheritance to define <code>Bird</code> as well as other things that fly, such as airplanes. Note that here, <em>everything</em> is starting out as a protocol! This allows you to encapsulate the functional concept in a way that doesn’t require a base class.</p>
<p>You’ll see how this makes the entire system more flexible when you start to define actual types next.</p>
<h2 id="Defining-Protocol-Conforming-Types"><a href="#Defining-Protocol-Conforming-Types" class="headerlink" title="Defining Protocol-Conforming Types"></a>Defining Protocol-Conforming Types</h2><p>Add the following <code>struct</code> definition to the bottom of the playground:</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">FlappyBird</span>: <span class="title">Bird</span>, <span class="title">Flyable</span> </span>&#123;</span><br><span class="line">      <span class="keyword">let</span> name: <span class="type">String</span></span><br><span class="line">      <span class="keyword">let</span> flappyAmplitude: <span class="type">Double</span></span><br><span class="line">      <span class="keyword">let</span> flappyFrequency: <span class="type">Double</span></span><br><span class="line">      <span class="keyword">let</span> canFly <span class="operator">=</span> <span class="literal">true</span></span><br><span class="line"></span><br><span class="line">      <span class="keyword">var</span> airspeedVelocity: <span class="type">Double</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="number">3</span> <span class="operator">*</span> flappyFrequency <span class="operator">*</span> flappyAmplitude</span><br><span class="line">      &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>This defines a new struct <code>FlappyBird</code>, which conforms to both the <code>Bird</code> and <code>Flyable</code> protocols. Its <code>airspeedVelocity</code> is calculated as a function of <code>flappyFrequency</code> and <code>flappyAmplitude</code>. Being flappy, it returns <code>true</code> for <code>canFly</code>. :]</p>
<p>Next, add the following two struct definitions to the bottom of the playground:</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">Penguin</span>: <span class="title">Bird</span> </span>&#123;</span><br><span class="line">      <span class="keyword">let</span> name: <span class="type">String</span></span><br><span class="line">      <span class="keyword">let</span> canFly <span class="operator">=</span> <span class="literal">false</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">SwiftBird</span>: <span class="title">Bird</span>, <span class="title">Flyable</span> </span>&#123;</span><br><span class="line">  <span class="keyword">var</span> name: <span class="type">String</span> &#123; <span class="keyword">return</span> <span class="string">&quot;Swift <span class="subst">\(version)</span>&quot;</span> &#125;</span><br><span class="line">  <span class="keyword">let</span> version: <span class="type">Double</span></span><br><span class="line">  <span class="keyword">let</span> canFly <span class="operator">=</span> <span class="literal">true</span></span><br><span class="line"></span><br><span class="line">  <span class="comment">// Swift is FASTER every version!</span></span><br><span class="line">  <span class="keyword">var</span> airspeedVelocity: <span class="type">Double</span> &#123; <span class="keyword">return</span> version <span class="operator">*</span> <span class="number">1000.0</span> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<p>A <code>Penguin</code> is a <code>Bird</code>, but cannot fly. A-ha — it’s a good thing you didn’t take the inheritance approach, and make all birds flyable after all! Using protocols allows you to define functional components and have any relevant object conform to them.</p>
<p>Already you can see some redundancies. Every type of <code>Bird</code> has to declare whether it <code>canFly</code> or not, even though there’s already a notion of <code>Flyable</code> in your system.<br><code>Bird</code>协议需要实现<code>canFly</code>参数，但是实际上遵守了<code>Flyable</code>协议就说明该对象的<code>canFlay</code>是true的。</p>
<h2 id="Extending-Protocols-With-Default-Implementations"><a href="#Extending-Protocols-With-Default-Implementations" class="headerlink" title="Extending Protocols With Default Implementations"></a>Extending Protocols With Default Implementations</h2><p>设置默认的实现，只要是遵守了<code>Flyable</code>协议那么<code>canFlay</code>都返回<code>true</code>。解决的办法就是设置协议的扩展</p>
<p>With protocol extensions, you can define default behavior for a protocol. Add the following just below the <code>Bird</code> protocol definition:</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">extension</span> <span class="title">Bird</span> </span>&#123;</span><br><span class="line">  <span class="comment">// Flyable birds can fly!</span></span><br><span class="line">  <span class="keyword">var</span> canFly: <span class="type">Bool</span> &#123; <span class="keyword">return</span> <span class="keyword">self</span> <span class="keyword">is</span> <span class="type">Flyable</span> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>This defines an extension on <code>Bird</code> that sets the default behavior for <code>canFly</code> to return <code>true</code> whenever the type is also <code>Flyable</code>. In other words, any <code>Flyable</code> bird no longer needs to explicitly declare so!</p>
<p><img src="media/15295785730512/protocols-extend-480x280.png" alt="protocols-extend"></p>
<p>Delete the <code>let canFly = ...</code> from <code>FlappyBird</code>, <code>SwiftBird</code> and <code>Penguin</code> struct declarations. You’ll see that the playground successfully builds since the protocol extension now handles that requirement for you.</p>
<h2 id="Why-Not-Base-Classes"><a href="#Why-Not-Base-Classes" class="headerlink" title="Why Not Base Classes?"></a>Why Not Base Classes?</h2><p>Protocol extensions and default implementations may seem similar to using a base class or even <a target="_blank" rel="noopener" href="https://en.wikipedia.org/wiki/Abstract_type">abstract classes</a> in other languages, but they offer a few key advantages in Swift:</p>
<ul>
<li>Because types can conform to more than one protocol, they can be <em>decorated</em> with default behaviors from multiple protocols. Unlike multiple inheritance of classes which some programming languages support, protocol extensions do not introduce any additional state.</li>
<li>Protocols can be adopted by classes, structs and enums. Base classes and inheritance are restricted to class types.</li>
</ul>
<p>In other words, protocol extensions provide the ability to define default behavior for <em>value</em> types and not just classes.</p>
<p>You’ve already seen this in action with a struct. Next, add the following enum definition to the end of the playground:</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">enum</span> <span class="title">UnladenSwallow</span>: <span class="title">Bird</span>, <span class="title">Flyable</span> </span>&#123;</span><br><span class="line">      <span class="keyword">case</span> african</span><br><span class="line">      <span class="keyword">case</span> european</span><br><span class="line">      <span class="keyword">case</span> unknown</span><br><span class="line">    </span><br><span class="line">      <span class="keyword">var</span> name: <span class="type">String</span> &#123;</span><br><span class="line">            <span class="keyword">switch</span> <span class="keyword">self</span> &#123;</span><br><span class="line">                  <span class="keyword">case</span> .african:</span><br><span class="line">                        <span class="keyword">return</span> <span class="string">&quot;African&quot;</span></span><br><span class="line">                  <span class="keyword">case</span> .european:</span><br><span class="line">                        <span class="keyword">return</span> <span class="string">&quot;European&quot;</span></span><br><span class="line">                  <span class="keyword">case</span> .unknown:</span><br><span class="line">                        <span class="keyword">return</span> <span class="string">&quot;What do you mean? African or European?&quot;</span></span><br><span class="line">            &#125;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">      <span class="keyword">var</span> airspeedVelocity: <span class="type">Double</span> &#123;</span><br><span class="line">            <span class="keyword">switch</span> <span class="keyword">self</span> &#123;</span><br><span class="line">                <span class="keyword">case</span> .african:</span><br><span class="line">                      <span class="keyword">return</span> <span class="number">10.0</span></span><br><span class="line">                <span class="keyword">case</span> .european:</span><br><span class="line">                      <span class="keyword">return</span> <span class="number">9.9</span></span><br><span class="line">                <span class="keyword">case</span> .unknown:</span><br><span class="line">                      <span class="built_in">fatalError</span>(<span class="string">&quot;You are thrown from the bridge of death!&quot;</span>)</span><br><span class="line">            &#125;</span><br><span class="line">      &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>As with any other value type, all you need to do is define the correct properties so <code>UnladenSwallow</code>conforms to the two protocols. Because it conforms to both <code>Bird</code> and <code>Flyable</code>. It also gets the default implementation for <code>canFly</code>!</p>
<p>Did you really think this tutorial involving <code>airspeedVelocity</code> wouldn’t include a Monty Python reference? :]</p>
<h2 id="Overriding-Default-Behavior"><a href="#Overriding-Default-Behavior" class="headerlink" title="Overriding Default Behavior"></a>Overriding Default Behavior</h2><p>但是对于<code>UnladenSwallow</code>的Enum的情况，如果是<code>.unknown</code>,因为遵守了<code>Bird</code>和<code>Flyable</code>协议，那么<code>.unknown</code>默认<code>canFlay</code>也会是<code>true</code>，怎么解决这个问题。解决的办法就是定义<code>UnladenSwallow</code>的扩展覆盖<code>canFlay</code>的实现。</p>
<p>Your <code>UnladenSwallow</code> type automatically got an implementation for <code>canFly</code> by virtue of conforming to the <code>Bird</code> protocol. However, you really want <code>UnladenSwallow.unknown</code> to return <code>false</code> for <code>canFly</code>. Is it possible to override the default implementation? Yes, it is. Add this to the end of your playground.</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">extension</span> <span class="title">UnladenSwallow</span> </span>&#123;</span><br><span class="line">  <span class="keyword">var</span> canFly: <span class="type">Bool</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">self</span> <span class="operator">!=</span> .unknown</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>Now only <code>.african</code> and <code>.european</code> will return <code>true</code> for <code>canFly</code>. Test it out by adding the following to the end of your playground:</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">UnladenSwallow</span>.unknown.canFly  <span class="comment">// false</span></span><br><span class="line"><span class="type">UnladenSwallow</span>.african.canFly  <span class="comment">// true</span></span><br><span class="line"><span class="type">Penguin</span>(name: <span class="string">&quot;King Penguin&quot;</span>).canFly  <span class="comment">// false</span></span><br></pre></td></tr></table></figure>

<p>In this way, it is possible to override properties and methods much like you can with virtual methods in object oriented programming.</p>
<h2 id="Extending-Protocols"><a href="#Extending-Protocols" class="headerlink" title="Extending Protocols"></a>Extending Protocols</h2><p>你也可以扩展标准协议，例如<code>CustomStringConvertible</code>的行为，例如你想给遵守了<code>Bird</code>协议的时候同事也遵守<code>CustomStringConvertible</code></p>
<p>You can utilize protocols from the standard library and also define <em>default</em> behaviors.<br>Modify the <code>Bird</code> protocol declaration to conform to the <code>CustomStringConvertible</code> protocol:<br>定义Bird协议也遵守<code>CustomStringConvertible</code>协议。遵守<code>CustomStringConvertible</code>协议，那么就意味着你需要定义<code>description</code>属性，也就是说所有遵守<code>Bird</code>协议的，你都需要给他们定义<code>description</code>属性，如果我想自动实现怎么办呢？</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">protocol</span> <span class="title">Bird</span>: <span class="title">CustomStringConvertible</span> </span>&#123;</span><br></pre></td></tr></table></figure>

<p>Conforming to <code>CustomStringConvertible</code> means your type needs to have a <code>description</code> property so it acts like a String. Does that mean you now have to add this property to <em>every</em> current and future <code>Bird</code> type?</p>
<p>Of course, there’s an easier way with protocol extensions. Add the code underneath the <code>Bird</code> definition:<br>定义<code>CustomStringConvertible</code>的扩展，但是这个扩展只是用在遵守了<code>Bird</code>协议的对象上。利用<code>canFly</code>属性自动提供两个版本的<code>description</code>的值。</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">extension</span> <span class="title">CustomStringConvertible</span> <span class="title">where</span> <span class="title">Self</span>: <span class="title">Bird</span> </span>&#123;</span><br><span class="line">  <span class="keyword">var</span> description: <span class="type">String</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> canFly <span class="operator">?</span> <span class="string">&quot;I can fly&quot;</span> : <span class="string">&quot;Guess I’ll just sit here :[&quot;</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>This extension will make the <code>canFly</code> property represent each <code>Bird</code> type’s <code>description</code> value.</p>
<p>To try it out, add the following to the bottom of the playground:</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">UnladenSwallow</span>.african</span><br></pre></td></tr></table></figure>


<p>You should see <code>“I can fly!”</code> appear in the assistant editor. But more notably, you just extended your own protocol!</p>
<h2 id="Effects-on-the-Swift-Standard-Library"><a href="#Effects-on-the-Swift-Standard-Library" class="headerlink" title="Effects on the Swift Standard Library"></a>Effects on the Swift Standard Library</h2><p>You’ve seen how protocol extensions are a great way to customize and extend the capabilities. What may surprise you is how the Swift team was able to use protocols to improve the way the Swift standard library is written as well.</p>
<p>Add the following code to the end of your playground:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">let numbers &#x3D; [10,20,30,40,50,60]</span><br><span class="line">let slice &#x3D; numbers[1...3]</span><br><span class="line">let reversedSlice &#x3D; slice.reversed()</span><br><span class="line"></span><br><span class="line">let answer &#x3D; reversedSlice.map &#123; $0 * 10 &#125;</span><br><span class="line">print(answer)</span><br></pre></td></tr></table></figure>


<p>This should look pretty straightforward, and you might even be able to guess the answer that is printed. What might be surprising are the types involved. <code>slice</code>, for example, is not an <code>Array</code> of integers but an <code>ArraySlice&lt;Int&gt;</code>. This special <em>wrapper type</em> acts as a view into the original array and avoids costly memory allocations that can quickly add up. Similarly, <code>reversedSlice</code> is actually a <code>ReversedRandomAccessCollection&lt;ArraySlice&lt;Int&gt;&gt;</code> which is again just a wrapper type view into the original array.</p>
<p><img src="media/15295785730512/secrets-480x178.png" alt="secrets"></p>
<p>Fortunately, the geniuses developing the standard library defined the <code>map</code> method as an extension to the <code>Sequence</code> protocol and all of the collection wrappers (of which there are dozens) to conform to this protocol. This makes it possible to call map on <code>Array</code> just as easily as it is <code>ReversedRandomAccessCollection</code>and not notice the difference. You will borrow this important design pattern shortly.</p>
<h2 id="Off-to-the-Races"><a href="#Off-to-the-Races" class="headerlink" title="Off to the Races"></a>Off to the Races</h2><p>So far you defined several <code>Bird</code> conforming types. Now add something totally different to the end of your playground.</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Motorcycle</span> </span>&#123;</span><br><span class="line">      <span class="function"><span class="keyword">init</span>(<span class="params">name</span>: <span class="type">String</span>)</span> &#123;</span><br><span class="line">            <span class="keyword">self</span>.name <span class="operator">=</span> name</span><br><span class="line">            speed <span class="operator">=</span> <span class="number">200</span></span><br><span class="line">      &#125;</span><br><span class="line">      <span class="keyword">var</span> name: <span class="type">String</span></span><br><span class="line">      <span class="keyword">var</span> speed: <span class="type">Double</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<p>This class that has nothing to do with birds or flying things you have defined so far. But you want to race motorcycles as well as penguins. Time to bring all of the pieces together.</p>
<h3 id="Bringing-it-Together"><a href="#Bringing-it-Together" class="headerlink" title="Bringing it Together"></a>Bringing it Together</h3><p>It is time to unify all of these disparate types with a common protocol for racing. You can do this with out even going back and touching the original model definitions. The fancy term for this is <em>retroactive modeling</em>. Just add the following to your playground:</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">protocol</span> <span class="title">Racer</span> </span>&#123;</span><br><span class="line">      <span class="keyword">var</span> speed: <span class="type">Double</span> &#123; <span class="keyword">get</span> &#125;  <span class="comment">// speed is the only thing racers care about</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">extension</span> <span class="title">FlappyBird</span>: <span class="title">Racer</span> </span>&#123;</span><br><span class="line">      <span class="keyword">var</span> speed: <span class="type">Double</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> airspeedVelocity</span><br><span class="line">      &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">extension</span> <span class="title">SwiftBird</span>: <span class="title">Racer</span> </span>&#123;</span><br><span class="line">      <span class="keyword">var</span> speed: <span class="type">Double</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> airspeedVelocity</span><br><span class="line">      &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">extension</span> <span class="title">Penguin</span>: <span class="title">Racer</span> </span>&#123;</span><br><span class="line">      <span class="keyword">var</span> speed: <span class="type">Double</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="number">42</span>  <span class="comment">// full waddle speed</span></span><br><span class="line">      &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">extension</span> <span class="title">UnladenSwallow</span>: <span class="title">Racer</span> </span>&#123;</span><br><span class="line">      <span class="keyword">var</span> speed: <span class="type">Double</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> canFly <span class="operator">?</span> airspeedVelocity : <span class="number">0</span></span><br><span class="line">      &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">extension</span> <span class="title">Motorcycle</span>: <span class="title">Racer</span> </span>&#123;&#125; <span class="comment">//本来就遵守了`Racer`协议</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> racers: [<span class="type">Racer</span>] <span class="operator">=</span></span><br><span class="line">      [<span class="type">UnladenSwallow</span>.african,</span><br><span class="line">       <span class="type">UnladenSwallow</span>.european,</span><br><span class="line">       <span class="type">UnladenSwallow</span>.unknown,</span><br><span class="line">       <span class="type">Penguin</span>(name: <span class="string">&quot;King Penguin&quot;</span>),</span><br><span class="line">       <span class="type">SwiftBird</span>(version: <span class="number">3.0</span>),</span><br><span class="line">       <span class="type">FlappyBird</span>(name: <span class="string">&quot;Felipe&quot;</span>, flappyAmplitude: <span class="number">3.0</span>, flappyFrequency: <span class="number">20.0</span>),</span><br><span class="line">       <span class="type">Motorcycle</span>(name: <span class="string">&quot;Giacomo&quot;</span>)</span><br><span class="line">  ]</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p>上面的代码，让所有的物种都准售了<code>Racer</code>协议，最后吧所有的物种都放在了一个<code>racers</code>的数组中。</p>
<p>In this code, you first define the protocol <code>Racer</code> and then you make all of the different types conform. Some types, such as <code>Motorcycle</code> conform trivially. Others, such as <code>UnladenSwallow</code> need a bit more logic. In the end, you have a bunch of conforming <code>Racer</code> types.</p>
<p>With all of the types conforming, you then create an array of racers.</p>
<h3 id="Top-Speed"><a href="#Top-Speed" class="headerlink" title="Top Speed"></a>Top Speed</h3><p>找到所有<code>Racer</code>里面速度最快的</p>
<p>Now it’s time to write a function that determines the top speed of the racers. Add this to the end of your playground:</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">topSpeed</span>(<span class="params">of</span> <span class="params">racers</span>: [<span class="type">Racer</span>])</span> -&gt; <span class="type">Double</span> &#123;</span><br><span class="line">  <span class="keyword">return</span> racers.max(by: &#123; <span class="variable">$0</span>.speed <span class="number">1</span>.speed &#125;)<span class="operator">?</span>.speed <span class="operator">??</span> <span class="number">0</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">topSpeed(of: racers) <span class="comment">// 3000</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>This function uses the standard library <code>max</code> to find the racer with the largest speed and return that. You return 0 if the user passes in an empty array in for <code>racers</code>.</p>
<p>Looks like it’s Swift 3 FTW. As if it were ever in doubt! :]</p>
<h3 id="Making-it-more-generic"><a href="#Making-it-more-generic" class="headerlink" title="Making it more generic"></a>Making it more generic</h3><p>让我们把它变得更通用一点，当你想传入切片到该函数的时候，这时候编译器报错了。</p>
<p>There is a problem though. Suppose you want to find the top speed for a subset (slice) of <code>racers</code>. Adding this to your playground you get an error:</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">topSpeed(of: racers[<span class="number">1</span><span class="operator">...</span><span class="number">3</span>]) <span class="comment">// ERROR</span></span><br></pre></td></tr></table></figure>

<p>Swift complains it cannot subscript a value of type <code>[Racer]</code> with an index of type <code>CountableClosedRange</code>. Slicing returns one of those wrapper types.</p>
<p>解决办法就是<br>The solution is to write your code against a common protocol instead of the concrete <code>Array</code>. Add the following before the <code>topSpeed(of:)</code> call.</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">topSpeed</span>(<span class="params">of</span> <span class="params">racers</span>: <span class="type">RacerType</span>)</span> -&gt; <span class="type">Double</span> <span class="keyword">where</span> <span class="type">RacerType</span>.<span class="type">Iterator</span>.<span class="type">Element</span> <span class="operator">==</span> <span class="type">Racer</span> &#123;</span><br><span class="line">  <span class="keyword">return</span> racers.max(by: &#123; <span class="variable">$0</span>.speed <span class="operator">&lt;</span> <span class="number">1</span>.speed &#125;)<span class="operator">?</span>.speed <span class="operator">??</span> <span class="number">0</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<p>This might look a bit scary, so let’s break it down. <code>RacerType</code> is the generic type for this function and it can be any type that conforms to the Swift standard library’s <code>Sequence</code> protocol. The <code>where</code> clause specifies that the element type of the sequence must conform to your <code>Racer</code> protocol. All <code>Sequence</code> types have an associated type named <code>Iterator</code> that can loop through types of <code>Element</code>. The actual method body is mostly the same as before.</p>
<p>This method works for any <code>Sequence</code> type including array slices.</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">topSpeed(of: racers[<span class="number">1</span><span class="operator">...</span><span class="number">3</span>]) <span class="comment">// 42</span></span><br></pre></td></tr></table></figure>


<h3 id="Making-it-More-Swifty"><a href="#Making-it-More-Swifty" class="headerlink" title="Making it More Swifty"></a>Making it More Swifty</h3><p>You can do even a little better. Borrowing from the standard library play book, you can extend <code>Sequence</code>type itself so that <code>topSpeed()</code> is readily discoverable. Add the following to the end of your playground:</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">extension</span> <span class="title">Sequence</span> <span class="title">where</span> <span class="title">Iterator</span>.<span class="title">Element</span> == <span class="title">Racer</span> </span>&#123;</span><br><span class="line">  <span class="function"><span class="keyword">func</span> <span class="title">topSpeed</span>()</span> -&gt; <span class="type">Double</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">self</span>.max(by: &#123; <span class="variable">$0</span>.speed <span class="number">1</span>.speed &#125;)<span class="operator">?</span>.speed <span class="operator">??</span> <span class="number">0</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">racers.topSpeed()        <span class="comment">// 3000</span></span><br><span class="line">racers[<span class="number">1</span><span class="operator">...</span><span class="number">3</span>].topSpeed() <span class="comment">// 42</span></span><br></pre></td></tr></table></figure>


<p>Now you have a method that is easily discoverable but only applies (and autocompletes) when you are dealing with sequences of racers.</p>
<h2 id="Protocol-Comparators"><a href="#Protocol-Comparators" class="headerlink" title="Protocol Comparators"></a>Protocol Comparators</h2><p>One Swift 3 improvement to protocols is how you create operator requirements.</p>
<p>Add the following to the bottom of the playground:</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">protocol</span> <span class="title">Score</span> </span>&#123;</span><br><span class="line">      <span class="keyword">var</span> value: <span class="type">Int</span> &#123; <span class="keyword">get</span> &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">RacingScore</span>: <span class="title">Score</span> </span>&#123;</span><br><span class="line">      <span class="keyword">let</span> value: <span class="type">Int</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<p>Having a <code>Score</code> protocol means that you can write code that treats all scores the same way. However, by having different concrete types such as <code>RacingScore</code> you are sure not to mix up these scores with style scores or cuteness scores. Thanks compiler!</p>
<p>You really want scores to be comparable so you can tell who has the high score. Before Swift 3, you needed to add global operator functions to conform to these protocols. Now you can define these static method that is part of the model. Do so now by replacing the definition of <code>Score</code> and <code>RacingScore</code> with the following:</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">protocol</span> <span class="title">Score</span>: <span class="title">Equatable</span>, <span class="title">Comparable</span> </span>&#123;</span><br><span class="line">      <span class="keyword">var</span> value: <span class="type">Int</span> &#123; <span class="keyword">get</span> &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">RacingScore</span>: <span class="title">Score</span> </span>&#123;</span><br><span class="line">      <span class="keyword">let</span> value: <span class="type">Int</span></span><br><span class="line"></span><br><span class="line">      <span class="keyword">static</span> <span class="function"><span class="keyword">func</span> <span class="title">==</span>(<span class="params">lhs</span>: <span class="type">RacingScore</span>, <span class="params">rhs</span>: <span class="type">RacingScore</span>)</span> -&gt; <span class="type">Bool</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> lhs.value <span class="operator">==</span> rhs.value</span><br><span class="line">            &#125;</span><br><span class="line">    </span><br><span class="line">      <span class="keyword">static</span> <span class="function"><span class="keyword">func</span>  <span class="title">Bool</span> </span>&#123;</span><br><span class="line">            <span class="keyword">return</span> lhs.value</span><br><span class="line">            &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>You just encapsulated all of the logic for <code>RacingScore</code> in one place. Now you can compare scores, and, with the magic of protocol extension default implementations, even use operators such as greater-than-or-equal-to that you never explicitly defined.</p>
<p>RacingScore(value: 150) &gt;= RacingScore(value: 130)  // true</p>
<h2 id="Where-To-Go-From-Here"><a href="#Where-To-Go-From-Here" class="headerlink" title="Where To Go From Here?"></a>Where To Go From Here?</h2><p>You can download the complete playground with all the code in this tutorial<br><a target="_blank" rel="noopener" href="https://koenig-media.raywenderlich.com/uploads/2016/11/SwiftProtocols.playground-1.zip">here</a>.</p>
<p>You’ve seen the power of protocol-oriented programming by creating your own simple protocols and extending them using protocol extensions. With default implementations, you can give existing protocols common and automatic behavior, much like a base class but better since it can apply to structs and enums too.</p>
<p>In addition, protocol extensions can not only be used to extend your own protocols, but can extend and provide default behavior to protocols in the Swift standard library, Cocoa, Cocoa Touch, or any third party library.</p>
<p>To continue learning more about protocols, you should read the <a target="_blank" rel="noopener" href="https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html">official Apple documentation</a>.</p>
<p>You can view an excellent WWDC session on <a target="_blank" rel="noopener" href="https://developer.apple.com/videos/wwdc/2015/?id=408">Protocol Oriented Programming</a> on Apple’s developer portal for a more in-depth look into the theory behind it all.</p>
<p>The rationale for operator conformance can be found on the <a target="_blank" rel="noopener" href="https://github.com/apple/swift-evolution/blob/master/proposals/0091-improving-operators-in-protocols.md">Swift evolution proposal</a>. You might also want to learn more about Swift collection protocols and <a target="_blank" rel="noopener" href="https://www.raywenderlich.com/139591/building-custom-collection-swift">learn how to build your own.</a></p>
<p>Finally, as with any “new” programming paradigm, it is easy to get overly exuberant and use it for <em>all the things</em>. This interesting <a target="_blank" rel="noopener" href="http://chris.eidhof.nl/post/protocol-oriented-programming/">blog post by Chris Eidhof</a> reminds us that we should beware of silver bullet solutions and using protocols everywhere “just because”.</p>
<p>Have any questions? Let us know in the forum discussion below!</p>

    </div>

    
    
    
        

  <div class="followme">
    <p>Welcome to my other publishing channels</p>

    <div class="social-list">

        <div class="social-item">
          <a target="_blank" class="social-link" href="/atom.xml">
            <span class="icon">
              <i class="fa fa-rss"></i>
            </span>

            <span class="label">RSS</span>
          </a>
        </div>
    </div>
  </div>


      <footer class="post-footer">
          <div class="post-tags">
              <a href="/tags/Ray-Wenderlich/" rel="tag"># Ray Wenderlich</a>
          </div>

        


        
    <div class="post-nav">
      <div class="post-nav-item">
    <a href="/2018/12/21/Swift/Magical%20Error%20Handling%20in%20Swift/" rel="prev" title="Magical Error Handling in Swift">
      <i class="fa fa-chevron-left"></i> Magical Error Handling in Swift
    </a></div>
      <div class="post-nav-item">
    <a href="/2018/12/21/Swift/JSON/" rel="next" title="JSON">
      JSON <i class="fa fa-chevron-right"></i>
    </a></div>
    </div>
      </footer>
    
  </article>
  
  
  



          </div>
          

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          Table of Contents
        </li>
        <li class="sidebar-nav-overview">
          Overview
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
          <div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-2"><a class="nav-link" href="#Getting-Started"><span class="nav-number">1.</span> <span class="nav-text">Getting Started</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Defining-Protocol-Conforming-Types"><span class="nav-number">2.</span> <span class="nav-text">Defining Protocol-Conforming Types</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Extending-Protocols-With-Default-Implementations"><span class="nav-number">3.</span> <span class="nav-text">Extending Protocols With Default Implementations</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Why-Not-Base-Classes"><span class="nav-number">4.</span> <span class="nav-text">Why Not Base Classes?</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Overriding-Default-Behavior"><span class="nav-number">5.</span> <span class="nav-text">Overriding Default Behavior</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Extending-Protocols"><span class="nav-number">6.</span> <span class="nav-text">Extending Protocols</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Effects-on-the-Swift-Standard-Library"><span class="nav-number">7.</span> <span class="nav-text">Effects on the Swift Standard Library</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Off-to-the-Races"><span class="nav-number">8.</span> <span class="nav-text">Off to the Races</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#Bringing-it-Together"><span class="nav-number">8.1.</span> <span class="nav-text">Bringing it Together</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Top-Speed"><span class="nav-number">8.2.</span> <span class="nav-text">Top Speed</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Making-it-more-generic"><span class="nav-number">8.3.</span> <span class="nav-text">Making it more generic</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Making-it-More-Swifty"><span class="nav-number">8.4.</span> <span class="nav-text">Making it More Swifty</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Protocol-Comparators"><span class="nav-number">9.</span> <span class="nav-text">Protocol Comparators</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Where-To-Go-From-Here"><span class="nav-number">10.</span> <span class="nav-text">Where To Go From Here?</span></a></li></ol></div>
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
  <p class="site-author-name" itemprop="name">HR</p>
  <div class="site-description" itemprop="description">Swimming 🏊 in the sea🌊of code!</div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives/">
        
          <span class="site-state-item-count">38</span>
          <span class="site-state-item-name">posts</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
            <a href="/categories/">
          
        <span class="site-state-item-count">9</span>
        <span class="site-state-item-name">categories</span></a>
      </div>
      <div class="site-state-item site-state-tags">
            <a href="/tags/">
          
        <span class="site-state-item-count">6</span>
        <span class="site-state-item-name">tags</span></a>
      </div>
  </nav>
</div>
  <div class="links-of-author motion-element">
      <span class="links-of-author-item">
        <a href="mailto:caohr@outlook.com" title="E-Mail → mailto:caohr@outlook.com" rel="noopener" target="_blank"><i class="fa fa-envelope fa-fw"></i>E-Mail</a>
      </span>
  </div>



      </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        

<div class="copyright">
  
  &copy; 
  <span itemprop="copyrightYear">2021</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">HR</span>
</div>
  <div class="powered-by">Powered by <a href="https://hexo.io/" class="theme-link" rel="noopener" target="_blank">Hexo</a> & <a href="https://pisces.theme-next.org/" class="theme-link" rel="noopener" target="_blank">NexT.Pisces</a>
  </div>

        








      </div>
    </footer>
  </div>

  
  <script src="/lib/anime.min.js"></script>
  <script src="/lib/velocity/velocity.min.js"></script>
  <script src="/lib/velocity/velocity.ui.min.js"></script>

<script src="/js/utils.js"></script>

<script src="/js/motion.js"></script>


<script src="/js/schemes/pisces.js"></script>


<script src="/js/next-boot.js"></script>




  















  

  

</body>
</html>
